/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "rtc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "AD9851.h"
#include "arm_math.h"
#include "tjc_usart_hmi.h"
#include "arm_const_structs.h"
#include "measure.h"
#include "math.h"
#include "OLED.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define FRAME_LENGTH 7
#define FIFO_SIZE 1024
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
//标志
u8 mode=MODE_MEASU, mea_step = MEAS_RI, freq_step = 0, plot_flag = 0, plot_clear = 0;
vu8 flag_readkey=0, flag_keyprocess=0, flag_mea_start=1, flag_ad_finish=0, flag_flash=0, flag_det_ad_start=0;

//DDS相关
u32 dds_freq = 1000;
//AD相关
u32 adc_buf[1536]={0};
u16 ad_Vin[512]={0}, ad_Iin[512]={0}, ad_Vout[512]={0};
float ad_Vin_fft[2048]={0}, ad_Vout_fft[2048]={0};
u8 cnt_AD_times=0;
//测量相关
//调试参数
u32 Vin_max=0, Vin_min=0xFFFFFFFF, Iin_max=0, Iin_min=0xFFFFFFFF, Vout_max=0, Vout_min=0xFFFFFFFF;
u32 Vin_Vpp=0, Iin_Vpp=0, Vout_Vpp=0, Vout_av=0, Av_100=0, Av_200k = 0;
double phase_diff, phase_diff_n;
u32 Vin_Vpp_n=0, Iin_Vpp_n=0, Vout_Vpp_n=0, Vout_av_n=0, Av_100_n=0, Av_200k_n = 0;
u32 Vout_sum=0;
u32 Vin_Vpp_sum=0, Iin_Vpp_sum=0,Vout_Vpp_sum=0,Vout_av_sum=0;
//输入电阻
u32 Ri_mea=MEA_INVALID;
//输出电阻
u32 Ro_mea=MEA_INVALID;
u8 Ro_times=10;
//放大倍数
u32 Av_mea=MEA_INVALID;
//三极管放大倍数
u32 beta_HF = MEA_INVALID;
//转折频率
u32 fH_mea=MEA_INVALID;//单位Hz，显示时除以1000
u32 Av_Afmea[10] = {0};//测量点的增益
u8 Av_dispdata[275];//显示数据，直线插值
//故障元件和原因
u8 Comp[7] = {0};//R1~R4，C1~C3，0表示没故障
u8 Comp_Reason = COMP_NONE;//见main.h宏定义
u8 Comp_num=0;
int class_type = 0;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void fresh(void);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_RTC_Init();
  MX_USART2_UART_Init();
  MX_ADC1_Init();
  MX_ADC2_Init();
  MX_ADC3_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
  // OLED初始化
  OLED_Init();        //OLED初始化
  OLED_Clear();
  OLED_ShowString(1, 1, "dds_freq:");  //1行1列显示字符串frequecncy
  //AD9851初始化
  AD9851_Reset();
  AD9851_Write(dds_freq);
  //串口屏相关初始化
  initRingBuffer();		//初始化环形缓冲区
  HAL_UART_Receive_IT(&TJC_UART, RxBuffer, 1);	//打开串口接收中断

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  uint32_t print_interval = 100; // 打印间隔（毫秒）
  uint32_t last_print_time = 0;   // 上次打印时间
  while (1)
  {

    uint32_t current_time = HAL_GetTick();
    // 每1秒显示一次数据
    if (current_time - last_print_time >= print_interval) {
      last_print_time = current_time;
      
      //模式选择

      //模式任务执行
      if (mode == MODE_MEASU){
        //参数测量模式
        if (flag_mea_start){
          //1.5s定时到且测量未完成，开始轮流检测各量
          if (mea_step == MEAS_RI){
            //输入电阻测量
            MeasRi();
            mea_step = MEAS_RO;
          }
          else if (mea_step == MEAS_RO){
            //输出电阻测量
            Ro_times++;
            if (Ro_times>=3){
              MeaRo();
              Ro_times = 0;
            }
            mea_step = MEAS_AV;
          }
          else if (mea_step == MEAS_AV){
            //放大倍数测量
            MeaAv();
            MeaHf();
            mea_step = MEAS_AF;
          }
          else if (mea_step == MEAS_AF){
            //幅频特性测量
            MeaAf();
            if (freq_step >= 10){
              sendAFDispdata();//发送幅频特性显示数据
              MeafH();//计算上限截止频率
              freq_step=0;
              mea_step = MEAS_NOR;
            }
          }
          else if (mea_step == MEAS_NOR){
            ADstart_detect();
            Av_100_n = Av_100;
            Av_200k_n = Av_200k;
            Vin_Vpp_n = Vin_Vpp;
            Iin_Vpp_n = Iin_Vpp;
            Vout_Vpp_n = Vout_Vpp;
            Vout_av_n = Vout_av;
            phase_diff_n = phase_diff;
            mea_step = MEAS_RI;
            flag_mea_start = 0;//测量结束
          }
        }
      } else if (mode == MODE_DETEC){
        //故障检测模式
        ADstart_detect();//参数测量
        errordetect();
      }
      fresh();
    OLED_ShowNum(2,1,dds_freq,8);
    OLED_ShowString(2,9,"Hz");
    OLED_ShowString(3,1,"Mode:");
    OLED_ShowNum(4,1,mode,3);
    }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
// 数据处理函数（分离模式选择逻辑）（在中断回调函数中被调用）
void processReceivedData(void) {
  uint16_t bufferLen = usize;  // 使用头文件定义的宏获取缓冲区长度

  // 检查是否有足够长度的帧
  if (bufferLen >= FRAME_LENGTH) {
    // 校验帧头帧尾（使用头文件定义的宏）
    if (u(0) == 0x55 && u(4) == 0xff && u(5) == 0xff && u(6) == 0xff) {
      // 处理模式切换命令
      handleModeCommand(u(1));

      // 删除已处理的数据帧
      udelete(FRAME_LENGTH);
    } else {
      // 帧格式错误，删除一个字节
      udelete(1);
    }
  }
}

// 模式命令处理函数
void handleModeCommand(uint8_t cmd) {
  switch (cmd) {
    case 0x01:
      mode = MODE_MEASU;
      // 初始化测量模式参数
      Ri_mea = MEA_INVALID;
      Ro_mea = MEA_INVALID;
      Av_mea = MEA_INVALID;
      beta_HF = MEA_INVALID;
      fH_mea = MEA_INVALID;
      flag_mea_start = 1;
      break;

    case 0x02:
      mode = MODE_DETEC;
      // 初始化故障检测模式参数
      for (int i = 0; i < 7; i++) {
        Comp[i] = 0;
      }
      Comp_num = 0;
      Comp_Reason = COMP_NONE;
      break;

    case 0x03:
      mode = MODE_NONE;
      break;

    case 0x04:
      plot_flag = 1;
      break;

    case 0x05:
      plot_clear = 1;
      break;

    default:
      break;
  }
}
// 更新显示
void fresh(void) {
  char str[100];
  sprintf(str,"t6.txt=\"%d\"",Ri_mea);
  tjc_send_string(str);
  sprintf(str,"t7.txt=\"%d\"",Ro_mea);
  tjc_send_string(str);
  sprintf(str,"t8.txt=\"%d\"",Av_mea);
  tjc_send_string(str);
  sprintf(str,"t18.txt=\"%d\"",fH_mea);
  tjc_send_string(str);
  // 画曲线
  if (plot_flag) {
    plot_flag = 0;
    // // 向曲线s0的通道1透传600个数据,addt指令不支持跨页面
    // for (i = 0; i < 600; i++) {
    //   Av_dispdata[i]=100+100*arm_sin_f32(6*3.1415926/300*i);
    // }
    tjc_send_string("addt s0.id,0,276\xff\xff\xff");

    // 等待适量时间
    HAL_Delay(100);

    for(int i = 0;i<276;i++)
    {
      uart_send_char((int)(Av_dispdata[i]));
    }

    // 确保透传结束，以免影响下一条指令
    tjc_send_string("\x01\xff\xff\xff");
  }
  // 清空曲线
  if (plot_clear) {
    tjc_send_string("cle s0.id,0\xff\xff\xff");
    plot_clear = 0;
  }
  flag_mea_start = 1;
  if (mode == MODE_DETEC) {

// 定义静态数组存储最近5个class_type值
static int class_type_history[5] = {0};
// 静态变量记录数组索引
static int history_index = 0;

// 将当前class_type值存入数组
class_type_history[history_index] = class_type;
// 更新索引，采用循环覆盖方式
history_index = (history_index + 1) % 5;

// 用于统计每个class_type值在这5个记录中出现的次数
int count[15] = {0};
for (int i = 0; i < 5; i++) {
    count[class_type_history[i]]++;
}

// 记录出现次数最多的class_type值及其出现次数
int most_common_type = -1;
int max_count = 0;
for (int i = 0; i < 15; i++) {
    if (count[i] > max_count) {
        max_count = count[i];
        most_common_type = i;
    }
}

// 仅当出现次数最多的值出现次数大于3时，才执行switch语句进行显示
if (max_count > 3) {
    switch(most_common_type) {
        case 0:  tjc_send_string("t9.txt=\"NONE\"\xff\xff\xff"); break;          // 0类：正常
        case 1:  tjc_send_string("t9.txt=\"R1 OPEN\"\xff\xff\xff"); break;        // 1类：R1OPEN
        case 2:  tjc_send_string("t9.txt=\"R2 OPEN\"\xff\xff\xff"); break;        // 2类：R2SHORT
        case 3:  tjc_send_string("t9.txt=\"R3 OPEN\"\xff\xff\xff"); break;        // 3类：R3SHORT
        case 4:  tjc_send_string("t9.txt=\"R4 OPEN\"\xff\xff\xff"); break;        // 4类：R1异常
        case 5:  tjc_send_string("t9.txt=\"R1 SHORT\"\xff\xff\xff"); break;        // 5类：R2异常
        case 6:  tjc_send_string("t9.txt=\"R2 SHORT\"\xff\xff\xff"); break;        // 6类：R3异常
        case 7:  tjc_send_string("t9.txt=\"R3 SHORT\"\xff\xff\xff"); break;        // 7类：C1异常
        case 8:  tjc_send_string("t9.txt=\"R4 SHORT\"\xff\xff\xff"); break;        // 8类：C2SHORT
        case 9:  tjc_send_string("t9.txt=\"C1 OPEN\"\xff\xff\xff"); break;        // 9类：C1OPEN
        case 10: tjc_send_string("t9.txt=\"C2 OPEN\"\xff\xff\xff"); break;        // 10类：C3异常
        case 11: tjc_send_string("t9.txt=\"C3 OPEN\"\xff\xff\xff"); break;        // 11类：C2OPEN
        case 12: tjc_send_string("t9.txt=\"C1 *2\"\xff\xff\xff"); break;        // 12类：无信号（全0数据）
        case 13: tjc_send_string("t9.txt=\"C2 *2\"\xff\xff\xff"); break;        // 13类：C2 *2
        case 14: tjc_send_string("t9.txt=\"C3 *2\"\xff\xff\xff"); break;        // 14类：C3 *2
        default: tjc_send_string("t9.txt=\"unkown\"\xff\xff\xff"); break;      // 默认：未知故障
    }
}

  }
}
// AD完成回调
void HAL_ADC_ConvCpltCallback (ADC_HandleTypeDef *hadc){	/* AD转换完成回调程序 */
  HAL_TIM_Base_Stop(&htim3);
  __HAL_TIM_SET_COUNTER(&htim3, 0);
  HAL_ADCEx_MultiModeStop_DMA(&hadc1);
  HAL_ADC_Stop(&hadc2);
  HAL_ADC_Stop(&hadc3);
  flag_ad_finish = 1;
}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
